﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

using sgsBase;

namespace gaClear
{
	public class BaseMsg
	{
		protected static CPCInterface _cpcintfc = new CPCInterface();
		private string _uid = "";
		private bool _iscpc = false;

		protected string _prodId;
		protected string _undlyId;
		protected string _undly_secTyp;
		protected string _undly_mmy;
		protected string _reqType;
		protected string _respType;
		protected string _reqTyp;
		protected string _secTyp;
		protected bool _showXml = true;
		protected string _errMsg;

		public void SetRqTyp(string secTyp)
		{
			if (secTyp == "FUT")
				_reqTyp = "104";
			else if (secTyp == "OOF")
				_reqTyp = "101";
			else
				_reqTyp = "102";
			_secTyp = secTyp;
		}

		#region Properties
		public string SecTyp
		{
			get { return _secTyp; }
			set { _secTyp = value; }
		}
		public string ProductId
		{
			get { return _prodId; }
			set { _prodId = value; }
		}
		public string UndlyId
		{
			get { return _undlyId; }
			set { _undlyId = value; }
		}
		public string UndlySecTyp
		{
			get { return _undly_secTyp; }
			set { _undly_secTyp = value; }
		}
		public string UndlyMMY
		{
			get { return _undly_mmy; }
			set { _undly_mmy = value; }
		}
		public string RequestType
		{
			get { return _reqType; }
			set { _reqType = value; }
		}
		public string ReqTyp
		{
			get { return _reqTyp; }
			set { _reqTyp = value; }
		}
		public string ResponseType
		{
			get { return _respType; }
			set { _respType = value; }
		}
		public string ErrMsg
		{
			get { return _errMsg; }
			set { _errMsg = value; }
		}
		public bool IsCPC
		{
			get { return _iscpc; }
			set { _iscpc = value; }
		}
		public CPCInterface CPCI
		{
			get { return _cpcintfc; }
			set { _cpcintfc = value; }
		}
		public string UID
		{
			get { return _uid; }
			set { _uid = value; }
		}

		#endregion

		protected void ResetUID()
		{
			_uid = "";
		}

		public BaseMsg()
		{
			_cpcintfc.Reset();
		}

		public bool Submit()
		{
			_errMsg = "";
			_cpcintfc.Message = callRequest();

			if (_cpcintfc.Message == "")
				return false;

			if (_showXml)
			{
				Program.MainForm.SentData = _cpcintfc.Message;
			}
			DateTime dtSent = DateTime.Now;

			if (_cpcintfc.SendMessage())
			{
				logData(dtSent);
				if (_showXml)
					Program.MainForm.ReplyData = _cpcintfc.ReplyMsg;
				callResponse();
				if (_errMsg == "")
					return true;
			}
			else
				logData(dtSent);

			return false;
		}

		private void logData(DateTime dtSent)
		{
			string data = "<xml>\n";
			data += "<sent><time>" + dtSent.ToString() + "</time><data>";
			data += _cpcintfc.Message + "</data></sent>\n";
			data += "<response><time>" + dtSent.ToString() + "</time><data>";
			data += _cpcintfc.ReplyMsg + "</data></response></xml>\n";

			Log.LogData(data, RequestType);
		}

		private string callRequest()
		{
			string rm = "";
			MemoryStream mem = new MemoryStream();
			XmlTextWriter xmlw = new XmlTextWriter(mem, System.Text.Encoding.UTF8);

			xmlw.WriteStartDocument();

			if (_iscpc)
				buildCPC(xmlw);

			if (!requestMsg(xmlw))
				return "";

			if (_iscpc)
				closeCPC(xmlw);

			xmlw.WriteEndDocument();
			xmlw.Flush();

			mem.Position = 0;
			StreamReader sr = new StreamReader(mem);
			rm = sr.ReadToEnd();
	
			xmlw.Close();
			mem.Close();

			return rm;
		}

		private void callResponse()
		{
			try
			{
				XmlDocument msg = _cpcintfc.ReplyXml;
				XmlNode root = msg.DocumentElement;

				foreach(XmlNode node in root.ChildNodes)
				{
					if (node.Name == "NotSure")
					{
						_errMsg = getAttr(node, "RejTxt");
					}
					else if (node.Name == ResponseType || (ResponseType== "Batch" && node.Name == "SecDef"))
					{
						string txt = getAttr(node, "RejTxt");
						if (txt != "")
						{
							_errMsg = txt;
							return;
						}

						txt = getAttr(node, "Txt");
						if (!txt.ToLower().StartsWith("valid"))
						{
							return;
						}
						else
							_errMsg = txt;

						responseParse(node);
					}
				}
			}
			catch (Exception ex)
			{
				Email.SendError(ex);
			}
		}


		protected virtual bool requestMsg( XmlTextWriter XmlW )
		{
			return true;
		}

		protected virtual bool instrmtMsg( XmlTextWriter XmlW )
		{
			return true;
		}

		protected virtual bool requestAttributes( XmlTextWriter XmlW )
		{
			return true;
		}

		protected virtual void responseParse(XmlNode node)
		{
		}

		protected void buildCPC( XmlTextWriter xmlw)
		{
			xmlw.WriteStartElement("FIXML");
			xmlw.WriteAttributeString("v", "5.0 SP2");
			xmlw.WriteAttributeString("s", "20090815");
			xmlw.WriteAttributeString("xv", "109");
			xmlw.WriteAttributeString("cv", "CME.0001");

			xmlw.WriteStartElement(RequestType);
			xmlw.WriteAttributeString("ReqID", UID);
			xmlw.WriteAttributeString("ReqTyp", _reqTyp);

			//' set up the request element, then end it
			requestAttributes(xmlw);

			xmlw.WriteStartElement("Hdr");
			xmlw.WriteAttributeString("TID", "CME");
			xmlw.WriteAttributeString("TSub", "CPAPI");
			xmlw.WriteAttributeString("SID", "1A3M"); // 'broker specific code
			xmlw.WriteAttributeString("SSub", Globals.UserName);
			xmlw.WriteEndElement();
		}

		protected void closeCPC(XmlTextWriter xmlw)
		{
			xmlw.WriteEndElement();
			xmlw.WriteEndElement();
		}

		protected string timestamp()
		{
			string str = DateTime.Now.ToString("yyyyMMddHHmmss");
			//string str = dt.ToString();
			//.Replace(":","");
			//str = str.Replace("/", "");
			//str = str.Replace(" ", "");
			//str = str.Replace("AM", "");
			//str = str.Replace("PM", "");
			return str;
		}

		protected string getAttr(XmlNode node, string val)
		{
			if (node.Attributes[val] == null)
				return "";
			return node.Attributes[val].InnerText;
		}
	}
}
